#!/bin/sh  /etc/rc.common
START=99
STOP=99

NAME=easucks
CNAME=FIFA助手
DESC="socks5 proxy redirector"
DAEMON=/usr/bin/ss-redir
PIDFILE=/var/run/$NAME.pid
TMPDIR=/tmp/$NAME
SSCONFIG=$TMPDIR/ss.json
PDNSDCONFIG=$TMPDIR/pdnsd.conf
DNSMASQ_CONFIG_DIR=/tmp/dnsmasq.d

luci_entry_button() {
    if [ $(grep $NAME /usr/lib/lua/luci/view/admin_web/network/index.htm|wc -l) -lt 1 ]; then
        sed -i 's/<ul id="advanced_setup">/<ul id="advanced_setup">\n<li><a href="<%=luci.dispatcher.build_url('"'"'admin_web'"'"','"'$NAME'"')%>">'"$CNAME"'<\/a><\/li>/' /usr/lib/lua/luci/view/admin_web/network/index.htm
    fi
}

ss_get_config() {
    lanip=$(uci get network.lan.ipaddr)
    ss_server_choice=$(uci get $NAME.ss_server_choice)
    ss_server_ipad=$(uci get $NAME.$ss_server_choice.ss_server_ipad)
    ss_server_port=$(uci get $NAME.$ss_server_choice.ss_server_port)
    ss_server_pass=$(uci get $NAME.$ss_server_choice.ss_server_pass)
    ss_server_meth=$(uci get $NAME.$ss_server_choice.ss_server_meth)
    ss_runnin_mode=$(uci get $NAME.$ss_server_choice.ss_runnin_mode)
    ss_remote_dnss=$(uci get $NAME.$ss_server_choice.ss_remote_dnss)
    ss_server_fsop=$(uci get $NAME.$ss_server_choice.ss_server_fsop)
    ss_local_port=$(uci get $NAME.$ss_server_choice.ss_local_port)

    # skip domain lookup if it is a IPv6 address
    [ $(echo $ss_server_ipad|grep -E ':'|wc -l) -lt 1 ] && {
        # nslookup if ss_server_ipad is a domain
        [ $(echo $ss_server_ipad|grep -E '[a-zA-Z]'|wc -l) -gt 0 ] && { ss_server_ipad=$(/usr/bin/resolveip -4 $ss_server_ipad); }
        # use domain if nslookup or regex command failed
        [ $(echo $ss_server_ipad|grep -E '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'|wc -l) -lt 1 ] && { s_server_ipad=$(uci get $NAME.$ss_server_choice.ss_server_ipad); }
    }
}

ss_create_config_file(){
    mkdir -p /tmp/$NAME/
    cat > $SSCONFIG << EOF
{
    "server": "$ss_server_ipad",
    "server_port": $ss_server_port,
    "local_address": "$lanip",
    "local_port": $ss_local_port,
    "password": "$ss_server_pass",
    "method": "$ss_server_meth",
    "timeout": 60,
    "fast_open": $ss_server_fsop,
    "mode": "tcp_only"
}
EOF
}

pdnsd_create_config_file(){
    mkdir -p /tmp/$NAME/
    cat > $PDNSDCONFIG <<EOF
global {
    perm_cache      = 65535;
    cache_dir       = /var/pdnsd;
    status_ctl      = on;
    server_ip       = 127.0.0.1;
    server_port     = 54;
    query_method    = tcp_only;
    tcp_server      = off;
    min_ttl         = 1d;
    max_ttl         = 1w;
    timeout         = 10;
    randomize_recs  = on;
    debug           = off;
    daemon          = on;
    verbosity       = 1;
    neg_rrs_pol     = on;
    neg_domain_pol  = on;
    par_queries     = 1;
}

server {
    label = "ss_remote_ddns";
    ip=$ss_remote_dnss;
    proxy_only = on;
    timeout = 5;
    caching = on;
    purge_cache = off;
}
EOF
    chmod 644 $PDNSDCONFIG
    ln -sf $PDNSDCONFIG /etc/pdnsd.conf
}

ss_iptables_add() {
    iptables -t nat -N $NAME-PREROUTING
    iptables -t nat -N $NAME-OUTPUT
    iptables -t nat -A PREROUTING -i br-lan -j $NAME-PREROUTING
    iptables -t nat -A OUTPUT -p tcp -j $NAME-OUTPUT

    iptables -t nat -A $NAME-PREROUTING -m set --match-set local dst -j RETURN
    iptables -t nat -A $NAME-OUTPUT -m set --match-set local dst -j RETURN
    iptables -t nat -A $NAME-PREROUTING -d $ss_server_ipad/32 -j RETURN
    iptables -t nat -A $NAME-OUTPUT -d $ss_server_ipad/32 -j RETURN
    iptables -t nat -A $NAME-OUTPUT -d $ss_remote_dnss -p tcp --dport 53 -j DNAT --to-destination $lanip:$ss_local_port

    [ $(ipset list ipsrc_force_list 2>/dev/null| wc -l) -eq 0 ] && { ipset -N ipsrc_force_list nethash; }
    [ $(ipset list ipdst_force_list 2>/dev/null| wc -l) -eq 0 ] && { ipset -N ipdst_force_list nethash; }
    [ $(ipset list ipsrc_ignore_list 2>/dev/null| wc -l) -eq 0 ] && { ipset -N ipsrc_ignore_list nethash; }
    [ $(ipset list ipdst_ignore_list 2>/dev/null| wc -l) -eq 0 ] && { ipset -N ipdst_ignore_list nethash; }
    ipset flush ipsrc_force_list
    ipset flush ipdst_force_list
    ipset flush ipsrc_ignore_list
    ipset flush ipdst_ignore_list
    cat /etc/$NAME/ipsrc.force | awk '{print "ipset add -q ipsrc_force_list "$0}'|sh
    cat /etc/$NAME/ipdst.force | awk '{print "ipset add -q ipdst_force_list "$0}'|sh
    cat /etc/$NAME/ipsrc.ignore | awk '{print "ipset add -q ipsrc_ignore_list "$0}'|sh
    cat /etc/$NAME/ipdst.ignore | awk '{print "ipset add -q ipdst_ignore_list "$0}'|sh
    iptables -t nat -A $NAME-PREROUTING -m set --match-set ipsrc_ignore_list src -j RETURN
    iptables -t nat -A $NAME-PREROUTING -m set --match-set ipdst_ignore_list dst -j RETURN
    iptables -t nat -A $NAME-PREROUTING -p tcp -m set --match-set ipsrc_force_list src -j REDIRECT --to-ports $ss_local_port
    iptables -t nat -A $NAME-PREROUTING -p tcp -m set --match-set ipdst_force_list dst -j REDIRECT --to-ports $ss_local_port
    iptables -t nat -A $NAME-OUTPUT -m set --match-set ipsrc_ignore_list src -j RETURN
    iptables -t nat -A $NAME-OUTPUT -m set --match-set ipdst_ignore_list dst -j RETURN
    iptables -t nat -A $NAME-OUTPUT -p tcp -m set --match-set ipsrc_force_list src -j DNAT --to-destination $lanip:$ss_local_port
    iptables -t nat -A $NAME-OUTPUT -p tcp -m set --match-set ipdst_force_list dst -j DNAT --to-destination $lanip:$ss_local_port

    case $ss_runnin_mode in
        gfwlist)
            [ $(ipset list gfwlist 2>/dev/null| wc -l) -eq 0 ] && { ipset -N gfwlist iphash; }
            [ $(ipset list ignorelist 2>/dev/null| wc -l) -eq 0 ] && { ipset -N ignorelist iphash; }
            ipset flush gfwlist
            ipset flush ignorelist

            # 注意：gfwlist模式会劫持DNS
            iptables -t nat -A $NAME-PREROUTING -p udp -m udp --dport 53 -j REDIRECT --to-ports 53
            iptables -t nat -A $NAME-PREROUTING -m set --match-set ignorelist dst -j RETURN
            iptables -t nat -A $NAME-OUTPUT -m set --match-set ignorelist dst -j RETURN
            iptables -t nat -A $NAME-PREROUTING -p tcp -m set --match-set gfwlist dst -j REDIRECT --to-ports $ss_local_port
            iptables -t nat -A $NAME-OUTPUT -p tcp -m set --match-set gfwlist dst -j DNAT --to-destination $lanip:$ss_local_port

            # 生成gfwlist.conf
            awk '{print "ipset=/"$1"/gfwlist"}' /etc/$NAME/gfw.list >> $DNSMASQ_CONFIG_DIR/gfwlist.conf
            # 生成强制走代理域名列表domain_force.conf
            sed -i 's/^[ ]*//;s/[ \t]*$//' /etc/$NAME/domain.force
            awk '{print "ipset=/"$1"/gfwlist"}' /etc/$NAME/domain.force >> $DNSMASQ_CONFIG_DIR/domain_force.conf
            # 生成强制不走代理域名列表domain_ignore.conf
            sed -i 's/^[ ]*//;s/[ \t]*$//' /etc/$NAME/domain.ignore
            awk '{print "ipset=/"$1"/ignorelist"}' /etc/$NAME/domain.ignore >> $DNSMASQ_CONFIG_DIR/domain_ignore.conf
            ;;
        game)
            iptables -t nat -A $NAME-PREROUTING -m set --match-set china dst -j RETURN
            iptables -t nat -A $NAME-OUTPUT -m set --match-set china dst -j RETURN
            iptables -t nat -A $NAME-PREROUTING -p tcp -j REDIRECT --to-ports $ss_local_port
            iptables -t nat -A $NAME-OUTPUT -p tcp -j DNAT --to-destination $lanip:$ss_local_port
            # 非域名列表模式时，域名黑名单和白名单转换成目的IP
            cat /etc/$NAME/domain.force | grep '\w' | awk '{print "/usr/bin/resolveip -4 "$0}'|sh|sort|uniq| awk '{print "ipset add -q ipdst_force_list "$0}'|sh
            cat /etc/$NAME/domain.ignore | grep '\w' | awk '{print "/usr/bin/resolveip -4 "$0}'|sh|sort|uniq| awk '{print "ipset add -q ipdst_ignore_list "$0}'|sh
            ;;
        web)
            iptables -t nat -A $NAME-PREROUTING -m set --match-set china dst -j RETURN
            iptables -t nat -A $NAME-OUTPUT -m set --match-set china dst -j RETURN
            iptables -t nat -A $NAME-PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports $ss_local_port
            iptables -t nat -A $NAME-OUTPUT -p tcp --dport 80 -j DNAT --to-destination $lanip:$ss_local_port
            iptables -t nat -A $NAME-PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports $ss_local_port
            iptables -t nat -A $NAME-OUTPUT -p tcp --dport 443 -j DNAT --to-destination $lanip:$ss_local_port
            # 非域名列表模式时，域名黑名单和白名单转换成目的IP
            cat /etc/$NAME/domain.force | grep '\w' | awk '{print "/usr/bin/resolveip -4 "$0}'|sh|sort|uniq| awk '{print "ipset add -q ipdst_force_list "$0}'|sh
            cat /etc/$NAME/domain.ignore | grep '\w' | awk '{print "/usr/bin/resolveip -4 "$0}'|sh|sort|uniq| awk '{print "ipset add -q ipdst_ignore_list "$0}'|sh
            ;;
        all)
            iptables -t nat -A $NAME-PREROUTING -p tcp -j REDIRECT --to-ports $ss_local_port
            iptables -t nat -A $NAME-OUTPUT -p tcp -j DNAT --to-destination $lanip:$ss_local_port
            ;;
    esac

    sed -i 's/^[ ]*//;s/[ \t]*$//' /etc/$NAME/mac.ignore
    local black_mac
    awk '{print $0}' /etc/$NAME/mac.ignore |
    while read black_mac; do
        [ -z "$black_mac" ] && continue
        iptables -t nat -I $NAME-PREROUTING -m mac --mac-source $black_mac -j RETURN
    done

}

ss_iptables_del() {
    iptables -t nat -D PREROUTING -i br-lan -j $NAME-PREROUTING 1>/dev/null 2>&1
    iptables -t nat -D OUTPUT -p tcp -j $NAME-OUTPUT 1>/dev/null 2>&1

    iptables -t nat -F $NAME-PREROUTING 1>/dev/null 2>&1
    iptables -t nat -X $NAME-PREROUTING 1>/dev/null 2>&1
    iptables -t nat -F $NAME-OUTPUT 1>/dev/null 2>&1
    iptables -t nat -X $NAME-OUTPUT 1>/dev/null 2>&1
}

ss_get_config
luci_entry_button

start() {
    insmod ipt_REDIRECT 2>/dev/null
    pdnsd_create_config_file
    ss_create_config_file
    $DAEMON -c $SSCONFIG -f $PIDFILE

    # 生成gfwlist.conf
    awk '{print "server=/"$1"/127.0.0.1#54"}' /etc/$NAME/gfw.list > $DNSMASQ_CONFIG_DIR/gfwlist.conf
    # 生成强制走代理域名列表domain_force.conf
    sed -i 's/^[ ]*//;s/[ \t]*$//' /etc/$NAME/domain.force
    awk '{print "server=/"$1"/127.0.0.1#54"}' /etc/$NAME/domain.force > $DNSMASQ_CONFIG_DIR/domain_force.conf
    # 生成强制不走代理域名列表domain_ignore.conf
    sed -i 's/^[ ]*//;s/[ \t]*$//' /etc/$NAME/domain.ignore
    awk '{print "server=/"$1"/#"}' /etc/$NAME/domain.ignore > $DNSMASQ_CONFIG_DIR/domain_ignore.conf

    ss_iptables_add

    /etc/init.d/dnsmasq restart
    /etc/init.d/pdnsd start
}

stop() {
    ss_iptables_del

    rm -rf $SSCONFIG $PDNSDCONFIG
    if [ -f $PIDFILE ]; then
        kill -9 `cat $PIDFILE`
        rm -f $PIDFILE
    fi
    kill -9 `ps | grep "$DAEMON -c $SSCONFIG" | grep -v grep | awk '{print $1}'` 2>/dev/null

    # 删除针对dnsmasq生成的域名列表
    rm -f $DNSMASQ_CONFIG_DIR/gfwlist.conf
    rm -f $DNSMASQ_CONFIG_DIR/domain_force.conf
    rm -f $DNSMASQ_CONFIG_DIR/domain_ignore.conf

    /etc/init.d/dnsmasq restart
    /etc/init.d/pdnsd stop
}

